home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 20 / Cream of the Crop 20 (Terry Blount) (1996).iso / os2 / eaclib.zip / EA.CPP next >
C/C++ Source or Header  |  1996-05-22  |  14KB  |  453 lines

  1. /* --------------------------------------------------------------------------
  2.  * $RCSfile: EA.cpp,v $
  3.  * $Revision: 1.1 $
  4.  * $Date: 1996/05/22 20:59:55 $
  5.  * $Author: Bablok $
  6.  * --------------------------------------------------------------------------
  7.  * Synopsis:
  8.  *
  9.  * Implementation of class EA. This class wraps the extended attributes API of
  10.  * OS/2.
  11.  *
  12.  * This file is part of the EA classlib package.
  13.  * Copyright Bernhard Bablok, 1996
  14.  *
  15.  * The EA classlib package is distributed in the hope that it will be
  16.  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
  17.  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  18.  *
  19.  * You may use the classes in the package to any extend you wish. You are
  20.  * allowed to change and copy the source of the classes, as long as you keep
  21.  * the copyright notice intact and as long as you document the changes you made.
  22.  *
  23.  * You are not allowed to sell the EA classlib package or a modified version
  24.  * thereof, but you may charge for costs of distribution media.
  25.  *
  26.  * --------------------------------------------------------------------------
  27.  * Change-Log:
  28.  *
  29.  * $Log: EA.cpp,v $
  30.  * Revision 1.1  1996/05/22 20:59:55  Bablok
  31.  * Initial revision
  32.  *
  33.  * -------------------------------------------------------------------------- */
  34.  
  35. #ifndef _IEXCEPT_
  36.    #include <iexcept.hpp>
  37. #endif
  38. #ifndef _IMSGTEXT_
  39.    #include <imsgtext.hpp>
  40. #endif
  41.  
  42. #ifndef EA_H
  43.    #include "EA.hpp"
  44. #endif
  45. #ifndef EALIST_H
  46.    #include "EAList.hpp"
  47. #endif
  48.  
  49. ///////////////////////////////////////////////////////////////////////////////
  50. //  Construct a multivalued EA from an EAList
  51. //
  52. EA::EA(const IString& name, const EAList& eaList, BYTE flag) : mName(name),
  53.                                                                    mFlag(flag) {
  54.  
  55.    if (!eaList.numberOfElements()) {
  56.       IInvalidRequest exc(IMessageText(ERR_EALIST_EMPTY,MSG_FILE),
  57.                                                      0,IException::recoverable);
  58.       ITHROW(exc);
  59.    }
  60.    mName.upperCase();
  61.  
  62.    // Calculate size of required buffer for mValue and check type   ------------
  63.  
  64.    EAList::Cursor current(eaList);
  65.    Boolean isSingleTyped = true;
  66.  
  67.    current.setToFirst();
  68.    USHORT  type   = current.element().mType,
  69.            length = 0;
  70.  
  71.    forCursor(current) {
  72.       const EA& ea = current.element();
  73.       isSingleTyped = type == ea.mType;
  74.       if (ea.isLengthPreceded())
  75.          length += sizeof(USHORT);
  76.       length += ea.mValue.length();
  77.    }
  78.  
  79.    // Query code page information   --------------------------------------------
  80.  
  81.    ULONG codePage, codePageLength;
  82.    APIRET rc = DosQueryCp(sizeof(codePage),&codePage,&codePageLength);
  83.  
  84.    if (rc == ERROR_CP_NOT_MOVED) {
  85.       IException exc(ISystemErrorInfo(rc,"DosQueryCp"),
  86.                                                     rc,IException::recoverable);
  87.       ITHROW(exc);
  88.    }
  89.  
  90.    // Allocate and fill buffer for mValue   ------------------------------------
  91.  
  92.    char *buffer, *p;
  93.    if (isSingleTyped)
  94.       length += 3*sizeof(USHORT);
  95.    else
  96.       length += 2*sizeof(USHORT) + eaList.numberOfElements()*sizeof(USHORT);
  97.    buffer = new char[length];
  98.    if (!buffer) {
  99.       IOutOfMemory exc(IMessageText(ERR_MEM_ALLOC_FAILED,MSG_FILE),0);
  100.       ITHROW(exc);
  101.    }
  102.    p = buffer;
  103.    *(USHORT*) p = (USHORT) codePage;
  104.    p += sizeof(USHORT);
  105.    *(USHORT*) p = (USHORT) eaList.numberOfElements();
  106.    p += sizeof(USHORT);
  107.    if (isSingleTyped) {
  108.       *(USHORT*) p = eaList.anyElement().mType;
  109.       p += sizeof(USHORT);
  110.    }
  111.  
  112.    forCursor(current) {
  113.       const EA& ea = current.element();
  114.       if (!isSingleTyped) {
  115.          *(USHORT*) p = ea.mType;
  116.          p += sizeof(USHORT);
  117.       }
  118.       if (ea.isLengthPreceded()) {
  119.          *(USHORT*) p = ea.mValue.length();
  120.          p += sizeof(USHORT);
  121.       }
  122.       memcpy(p,(char*) ea.mValue,ea.mValue.length());
  123.       p += ea.mValue.length();
  124.    }
  125.  
  126.    // set mValue and clean up resources   --------------------------------------
  127.  
  128.    mValue = IString(buffer,length);
  129.    if (isSingleTyped)
  130.       mType  = EAT_MVST;
  131.    else
  132.       mType  = EAT_MVMT;
  133.    delete buffer;
  134. }
  135.  
  136.  
  137. ///////////////////////////////////////////////////////////////////////////////
  138. //  Construct an EA from a FEA2-structure
  139. //
  140. EA::EA(FEA2* fea2) {
  141.    mName = fea2->szName;
  142.    mFlag = fea2->fEA;
  143.    if (fea2->cbValue) {
  144.       char* val = (char*) fea2 + sizeof(FEA2) + fea2->cbName;
  145.       mType  = *(USHORT*) val;                        // first word is type
  146.       if (isLengthPreceded())                         // second word is length
  147.          mValue = IString(val+2*sizeof(USHORT),fea2->cbValue-2*sizeof(USHORT));
  148.       else
  149.          mValue = IString(val+sizeof(USHORT),fea2->cbValue - sizeof(USHORT));
  150.    } else {
  151.       mValue = "";
  152.       mType  = EAT_ASCII;
  153.    }
  154. }
  155.  
  156.  
  157. ///////////////////////////////////////////////////////////////////////////////
  158. //  Read an EA from a given file. If the given EA does not exist, the value
  159. //  is set to "".
  160. //
  161. EA& EA::read(PVOID fileRef, Boolean isPathName) {
  162.  
  163.    if (mName == "") {
  164.       IInvalidRequest exc(IMessageText(ERR_NO_EA_NAME,MSG_FILE),
  165.                                                      0,IException::recoverable);
  166.       ITHROW(exc);
  167.    }
  168.  
  169.    // set up EA list and query EA   --------------------------------------------
  170.  
  171.    EAOP2 eaBuffer;
  172.    eaBuffer.fpGEA2List = createGEA2LIST();
  173.    eaBuffer.fpFEA2List = createFEA2LISTBuffer(fileRef,isPathName);
  174.    eaBuffer.oError     = 0;
  175.    APIRET rc;
  176.    if (isPathName)
  177.       rc = DosQueryPathInfo((PSZ)fileRef,FIL_QUERYEASFROMLIST,&eaBuffer,
  178.                                                                  sizeof(EAOP2));
  179.    else
  180.       rc = DosQueryFileInfo(*(HFILE*)fileRef,FIL_QUERYEASFROMLIST,&eaBuffer,
  181.                                                                  sizeof(EAOP2));
  182.    if (rc) {
  183.       delete eaBuffer.fpGEA2List;
  184.       delete eaBuffer.fpFEA2List;
  185.       IString api;
  186.       if (isPathName)
  187.          api = "DosQueryPathInfo";
  188.       else
  189.          api = "DosQueryFileInfo";
  190.       IException exc(ISystemErrorInfo(rc,api),rc,IException::recoverable);
  191.       ITHROW(exc);
  192.    }
  193.  
  194.    // convert result to EA   ---------------------------------------------------
  195.  
  196.    *this = EA(&eaBuffer.fpFEA2List->list[0]);
  197.    delete eaBuffer.fpGEA2List;
  198.    delete eaBuffer.fpFEA2List;
  199.    return *this;
  200. }
  201.  
  202.  
  203. ///////////////////////////////////////////////////////////////////////////////
  204. //  Write an EA to the given file.
  205. //
  206. EA& EA::write(PVOID fileRef, Boolean isPathName) {
  207.  
  208.    if (mName == "") {
  209.       IInvalidRequest exc(IMessageText(ERR_NO_EA_NAME,MSG_FILE),
  210.                                                      0,IException::recoverable);
  211.       ITHROW(exc);
  212.    }
  213.  
  214.    EAOP2 eaBuffer;
  215.    eaBuffer.fpGEA2List = 0;
  216.    eaBuffer.fpFEA2List = createFEA2LIST();
  217.    eaBuffer.oError     = 0;
  218.    APIRET rc;
  219.    if (isPathName)
  220.       rc = DosSetPathInfo((PSZ)fileRef,FIL_QUERYEASIZE,&eaBuffer,sizeof(EAOP2),
  221.                                                                   DSPI_WRTTHRU);
  222.    else
  223.       rc = DosSetFileInfo(*(HFILE*)fileRef,FIL_QUERYEASIZE,
  224.                                                        &eaBuffer,sizeof(EAOP2));
  225.    delete eaBuffer.fpFEA2List;
  226.    if (rc) {
  227.       IString api;
  228.       if (isPathName)
  229.          api = "DosSetPathInfo";
  230.       else
  231.          api = "DosSetFileInfo";
  232.       IException exc(ISystemErrorInfo(rc,api),rc,IException::recoverable);
  233.       ITHROW(exc);
  234.    }
  235.    return *this;
  236. }
  237.  
  238.  
  239. ///////////////////////////////////////////////////////////////////////////////
  240. //  Remove an EA from the given file.
  241. //
  242. EA& EA::remove(PVOID fileRef, Boolean isPathName) {
  243.    EA rem(*this);
  244.    rem.mValue = "";
  245.    rem.write(fileRef,isPathName);
  246.    return *this;
  247. }
  248.  
  249.  
  250. ///////////////////////////////////////////////////////////////////////////////
  251. //  Determine if data-area of EA is preceded by length (static version)
  252. //
  253. Boolean EA::isLengthPreceded(USHORT type) {
  254.    switch (type) {
  255.       case EAT_BINARY:
  256.       case EAT_ASCII:
  257.       case E